﻿/*
 * Created by SharpDevelop.
 * User: amb
 * Date: 30/05/2014
 * Time: 15:39
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;
using Rich.Newman;
//using System.Runtime.InteropServices;

namespace JdFormsDll
{

    internal enum ButtonsType : byte { None, Minimize, Resize, Close }
    public enum Shadow : byte { None, Low, Normal, Hight }
    public enum Percent : byte
    {
        Percent0, Percent10, Percent20, Percent30, Percent40, Percent50,
        Percent60, Percent70, Percent80, Percent90, Percent100
    }

    /// <summary>
    /// Description of JdHelper.
    /// </summary>
    internal static class JdHelper
    {

        private const int iSize = 24;

        internal static Rectangle ClientArea(Rectangle rectangle, Padding padding)
        {
            if (padding == Padding.Empty) return rectangle;
            return new Rectangle(rectangle.X + padding.Left,
                                rectangle.Y + padding.Top,
                                rectangle.Width - padding.Horizontal,
                                rectangle.Height - padding.Vertical);
        }

        internal static Rectangle TitleBar(Rectangle rectangle, Padding padding)
        {
            return new Rectangle(rectangle.X + padding.Left,
                rectangle.Y + padding.Bottom,
                rectangle.Width - padding.Horizontal,
                padding.Top - 2 * padding.Bottom);
        }

        internal static Rectangle CaptionArea(Rectangle rectangle, Padding padding)
        {
            Rectangle r = TitleBar(rectangle, padding);
            Rectangle rLeft = IconArea(rectangle, padding);
            Rectangle rRight = MinimizeArea(rectangle, padding);
            return new Rectangle(rLeft.Right,
                                  r.Top,
                                  rRight.Left - rLeft.Right,
                                  r.Height);
        }

        internal static int IsOnResizeArea(Point point, Rectangle rectangle, Padding padding)
        {
            int shift = 6;
            Rectangle r = new Rectangle(rectangle.Left, rectangle.Top + shift, padding.Left, rectangle.Height - shift * 2);
            if (r.Contains(point)) return 0x000A; //HTLEFT
            r = new Rectangle(rectangle.Right - padding.Right, rectangle.Top + shift, padding.Right, rectangle.Height - shift * 2);
            if (r.Contains(point)) return 0x000B; //HTRIGHT 
            r = new Rectangle(rectangle.Left + shift, rectangle.Top, rectangle.Width - shift * 2, padding.Bottom);
            if (r.Contains(point)) return 0x000C; //HTTOP
            r = new Rectangle(rectangle.Left, rectangle.Top, shift, shift);
            if (r.Contains(point)) return 0x000D; //HTTOPLEFT  
            r = new Rectangle(rectangle.Right - shift, rectangle.Top, shift, shift);
            if (r.Contains(point)) return 0x000E; //HTTOPRIGHT  
            r = new Rectangle(rectangle.Left + shift, rectangle.Bottom - padding.Bottom, rectangle.Width - shift * 2, padding.Bottom);
            if (r.Contains(point)) return 0x000F; //HTBOTTOM 
            r = new Rectangle(rectangle.Left, rectangle.Bottom - shift, shift, shift);
            if (r.Contains(point)) return 0x0010; //HTBOTTOMLEFT  
            r = new Rectangle(rectangle.Right - shift, rectangle.Bottom - shift, shift, shift);
            if (r.Contains(point)) return 0x0011; //HTBOTTOMRIGHT   			
            return 0;
        }

        internal static Rectangle TitleBorderLeft(Rectangle rectangle, Padding padding)
        {
            Rectangle rIcon = IconArea(rectangle, padding);
            return new Rectangle(rIcon.Left - iSize / 2, rIcon.Top, iSize / 2, rIcon.Height);
        }

        internal static Icon MyIcon { get; set; }

        internal static Rectangle IconArea(Rectangle rectangle, Padding padding)
        {
            Rectangle r = TitleBar(rectangle, padding);
            int w = iSize;
            int h = iSize;
            if (MyIcon != null)
            {
                w = MyIcon.Width + 8;
                h = MyIcon.Height + 8;
            }
            int s = r.Height / 2 - h / 2;
            return new Rectangle(r.Left + iSize / 2, r.Top + s, w, h);
        }

        internal static Rectangle TitleBorderRight(Rectangle rectangle, Padding padding)
        {
            Rectangle r = TitleBar(rectangle, padding);
            Rectangle rLeft = TitleBorderLeft(rectangle, padding);
            return new Rectangle(r.Right - iSize / 2, rLeft.Top, iSize / 2, rLeft.Height);
        }

        internal static Rectangle CloseArea(Rectangle rectangle, Padding padding)
        {
            Rectangle rRight = TitleBorderRight(rectangle, padding);
            return new Rectangle(rRight.Left - iSize, rRight.Top, iSize, rRight.Height);
        }

        internal static Rectangle ResizeArea(Rectangle rectangle, Padding padding)
        {
            Rectangle r = CloseArea(rectangle, padding);
            return new Rectangle(r.Left - r.Width, r.Top, r.Width, r.Height);
        }

        internal static Rectangle MinimizeArea(Rectangle rectangle, Padding padding)
        {
            Rectangle r = ResizeArea(rectangle, padding);
            return new Rectangle(r.Left - r.Width, r.Top, r.Width, r.Height);
        }

        private static void DrawRectangle(Graphics gp, Rectangle r, Color c, ButtonsType type, FormWindowState state = FormWindowState.Normal)
        {
            string str = "r";
            if (type == ButtonsType.Minimize) str = "0";
            if (type == ButtonsType.Resize) str = (state == FormWindowState.Maximized) ? "2" : "1";
            using (Font fnt = new Font("Webdings", 12f, FontStyle.Regular))
            {
                using (StringFormat sf = new StringFormat())
                {
                    sf.Alignment = StringAlignment.Center;
                    sf.LineAlignment = StringAlignment.Center;
                    gp.DrawString(str, fnt, new SolidBrush(c), r, sf);
                }
            }
        }

        internal static void DrawMinimize(Graphics gp, Rectangle rectangle, Color color, Padding padding)
        {
            Rectangle r = MinimizeArea(rectangle, padding);
            DrawRectangle(gp, r, color, ButtonsType.Minimize);
        }

        internal static void DrawResize(Graphics gp, Rectangle rectangle, Color color, Padding padding, FormWindowState state)
        {
            Rectangle r = ResizeArea(rectangle, padding);
            DrawRectangle(gp, r, color, ButtonsType.Resize, state);
        }

        internal static void DrawClose(Graphics gp, Rectangle rectangle, Color color, Padding padding)
        {
            Rectangle r = CloseArea(rectangle, padding);
            DrawRectangle(gp, r, color, ButtonsType.Close);
        }

        internal static void DrawBorder3D(Graphics gp, Rectangle rectangle, Border3DStyle style)
        {
            rectangle.Inflate(1, 1);
            ControlPaint.DrawBorder3D(gp, rectangle, style);
        }

        internal static GraphicsPath RoundRect(RectangleF rectangle, float r1, float r2, float r3, float r4)
        {
            float x = rectangle.X;
            float y = rectangle.Y;
            float w = rectangle.Width;
            float h = rectangle.Height;
            GraphicsPath gph = new GraphicsPath();
            gph.AddBezier(x, y + r1, x, y, x + r1, y, x + r1, y);
            gph.AddLine(x + r1, y, x + w - r2, y);
            gph.AddBezier(x + w - r2, y, x + w, y, x + w, y + r2, x + w, y + r2);
            gph.AddLine(x + w, y + r2, x + w, y + h - r3);
            gph.AddBezier(x + w, y + h - r3, x + w, y + h, x + w - r3, y + h, x + w - r3, y + h);
            gph.AddLine(x + w - r3, y + h, x + r4, y + h);
            gph.AddBezier(x + r4, y + h, x, y + h, x, y + h - r4, x, y + h - r4);
            gph.AddLine(x, y + h - r4, x, y + r1);
            return gph;
        }

        internal static void DrawRectBorder
            (
            Graphics gp, 
            Rectangle rectangle,
            Color backcolor,
            Color backcolorshadow,
            Percent colorsdifferencepercent,
            bool showborder, 
            bool drawbackground = true
            )
        {
            rectangle.Inflate(2, 2);
            Color c = Color.Empty;
            if (backcolor.IsEqualTo(backcolorshadow, colorsdifferencepercent))
            {
                if (backcolor.IsLightColor())
                    c = backcolor.Change(-.5d);
                else
                    c = backcolor.Change(.5d);
            }
            else
            {
                c = backcolorshadow;
            }
            using (GraphicsPath gph = RoundRect(rectangle, 2, 2, 2, 2))
            {
                if (drawbackground) gp.FillPath(new SolidBrush(backcolor), gph);
                if (showborder)
                {
                    using (Pen p = new Pen(c, 1))
                    {
                        p.Alignment = PenAlignment.Center;
                        p.LineJoin = LineJoin.Round;
                        gp.DrawPath(p, gph);
                    }
                }
            }
        }

        internal static void DrawRect
            (
            Graphics gp, 
            Rectangle rectangle, 
            Color backcolor, 
            Color backcolorshadow,
            float round,
            bool drawborder,
            Percent colorsdifferencepercent
            )
        {
            rectangle.Inflate(2, 2);
            using (GraphicsPath gph = RoundRect(rectangle, round, round, round, round))
            {
                using (LinearGradientBrush lgb = new LinearGradientBrush(rectangle, backcolor, backcolorshadow, LinearGradientMode.Vertical))
                {
                    ColorBlend colorBlend = new ColorBlend();
                    Color[] colors = new Color[5];
                    colors[0] = backcolor;
                    colors[4] = backcolor;
                    colors[2] = backcolor.Mix(backcolorshadow, .5d);
                    colors[1] = backcolorshadow.Mix(colors[2], .5d);
                    colors[3] = backcolor.Mix(colors[2], .5d);

                    float[] relativePositions = { 0.0f, 0.03f, 0.4f, 0.6f, 1.0f };
                    colorBlend.Colors = colors;
                    colorBlend.Positions = relativePositions;
                    lgb.InterpolationColors = colorBlend;
                    gp.FillPath(lgb, gph);
                }
                if (drawborder)
                {
                    if (backcolor.IsEqualTo(backcolorshadow, colorsdifferencepercent))
                    {
                        if (backcolor.IsLightColor())
                            gp.DrawPath(new Pen(backcolor.Change(-.5d), 1), gph);
                        else
                            gp.DrawPath(new Pen(backcolor.Change(.5d), 1), gph);
                    }
                    else
                    {
                        gp.DrawPath(new Pen(backcolorshadow, 1), gph);
                    }
                }
            }
        }

        public static Bitmap MsgBoxIcon(MessageBoxIcon type)
        {
            string text = string.Empty;
            Bitmap bmp = new Bitmap(24, 24);

            bmp.MakeTransparent(Color.White);
            Graphics gp = Graphics.FromImage(bmp);
            gp.SmoothingMode = SmoothingMode.HighQuality;
            gp.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
            Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
            Color c1 = Color.White;
            if (type == MessageBoxIcon.Question)
            {
                c1 = Color.Green;
                text = "?";
            }
            if (type == MessageBoxIcon.Stop)
            {
                c1 = Color.Red;
                text = "X";
            }
            if (type == MessageBoxIcon.Exclamation)
            {
                c1 = Color.Yellow;
                text = "!";
            }
            if (type == MessageBoxIcon.Information)
            {
                c1 = Color.Blue;
                text = "i";
            }
            if (!string.IsNullOrEmpty(text))
            {
                using (GraphicsPath gph = new GraphicsPath())
                {
                    using (Font fnt = new Font("Courier New", 24f, FontStyle.Bold))
                    {
                        using (StringFormat sf = new StringFormat())
                        {
                            sf.Alignment = StringAlignment.Center;
                            sf.LineAlignment = StringAlignment.Near;
                            gph.AddString(text, fnt.FontFamily, (int)fnt.Style, (float)fnt.Size, rect, sf);
                            using (Pen p = new Pen(c1.Mix(Color.White, .80d), 6))
                            {
                                p.Alignment = PenAlignment.Center;
                                p.LineJoin = LineJoin.Round;
                                gp.DrawPath(p, gph);
                            }
                            gp.FillPath(new SolidBrush(c1), gph);
                        }
                    }
                }
            }
            return bmp;
        }
    }

    public static class Table
    {
        public static MyForm Form { get; set; }

        public static Color BackColor(Color color)
        {
            if (Form == null) return color;
            return Form.BackColor;
        }

        public static Color BorderColor(Color color)
        {
            if (Form == null) return color;
            if (Form.BackColor.IsEqualTo(Form.BackColorShadow, Form.ColorsDifferencePercent))
            {
                if (Form.BackColor.IsLightColor()) return Form.BackColor.Change(-.5d);
                else return Form.BackColor.Change(.5d);
            }
            else return Form.BackColorShadow;
        }

        public static Color BackColorPressed(Color color)
        {
            if (Form == null) return color;
            Color c = Color.Empty;
            double p = 0;
            double d = Form.BackColor.Diff(Form.BackColorShadow);
            if (Form.BackColor.IsEqualTo(Form.BackColorShadow, Form.ColorsDifferencePercent))
            {
                p = (double)(Form.BackColor.IsLightColor() ? -.15d : .75d);
                c = Form.BackColor.Change(p);
            }
            else if (d > 0d) c = Form.BackColor.Mix(Form.BackColorShadow, Math.Abs(d));
            else c = Form.BackColor.Mix(Form.BackColorShadow, 1d - Math.Abs(d));
            return c;
        }

        public static Color BackColorSelected(Color color)
        {
            if (Form == null) return color;
            Color c = Color.Empty;
            double p = 0;
            double d = Form.BackColor.Diff(Form.BackColorShadow);
            if (Form.BackColor.IsEqualTo(Form.BackColorShadow, Form.ColorsDifferencePercent))
            {
                p = (double)(Form.BackColor.IsLightColor() ? -.1d : .5d);
                c = Form.BackColor.Change(p);
            }
            else if (d > 0d) c = Form.BackColor.Mix(Form.BackColorShadow, Math.Abs(d) / 2d);
            else c = Form.BackColor.Mix(Form.BackColorShadow, (1d - Math.Abs(d)) / 2d);
            return c;
        }

        public static Color ForeColor(Color color)
        {
            if (Form == null) return color.BlackAndWhite();
            return Form.BackColor.BlackAndWhite();
        }
    }

    public static class ColorExtensions
    {
        public static Color Mix(this Color c, Color color, double percent)
        {
            int a = (int)(c.A * (1d - percent) + color.A * percent);
            int r = (int)(c.R * (1d - percent) + color.R * percent);
            int g = (int)(c.G * (1d - percent) + color.G * percent);
            int b = (int)(c.B * (1d - percent) + color.B * percent);
            if (a < 0) a = 0;
            if (a > 255) a = 255;
            if (r < 0) r = 0;
            if (r > 255) r = 255;
            if (g < 0) g = 0;
            if (g > 255) g = 255;
            if (b < 0) b = 0;
            if (b > 255) b = 255;
            return Color.FromArgb(a, r, g, b);
        }

        public static bool IsEqualTo(this Color c, Color color,Percent tolerance)
        {
            double d = c.Diff(color);
            double t = (double)((int)tolerance * .1d);
            return Math.Abs(d) < t;
        }

        public static double Diff(this Color c, Color color)
        {
            HSLColor c1 = new HSLColor(c);
            HSLColor c2 = new HSLColor(color);
            return (c2.Luminosity - c1.Luminosity) / c1.Scale;
        }

        public static Color Change(this Color c, double percent)
        {
            if (percent == 0d) return c;
            HSLColor c1 = new HSLColor(c);
            if (c1.Luminosity != 0d)
            {
                if (percent > 0d) percent = 1d + percent; else percent = 1d - Math.Abs(percent);
                double l = c1.Luminosity * percent;
                if (l < 0d) l = 0d;
                if (l > c1.Scale) l = c1.Scale;
                c1.Luminosity = l;
            }
            else c1.Luminosity = c1.Scale * Math.Abs(percent);
            return c1;
        }

        public static bool IsLightColor(this Color c)
        {
            HSLColor c1 = new HSLColor(c);
            return (c1.Luminosity / c1.Scale) >= .5d;
        }

        public static Color BlackAndWhite(this Color color)
        {
            if (color.IsLightColor()) return Color.Black;
            return Color.White;
        }
    }
}
